package model;

import interfaces.PipelineI;
import interfaces.TaskI;

import java.util.Vector;

public class Pipeline<INOUT> implements PipelineI<INOUT> {

	private Vector<TaskI> tasks = new Vector<TaskI>();
	private Vector<Stage> workers = null;
	private Vector<FIFOBuffer> connectors = null;
	private int workerCount = 0;
	// boolean dbg = true;
	boolean dbg = false;

	/*
	 * (non-Javadoc)
	 * 
	 * @see parallelpattern.PipelineI#setWorkers(int)
	 */
	@Override
	public void setWorkers(int n) {

		this.workers = new Vector<Stage>();
		this.workers.setSize(n);
		this.workerCount = n;

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see parallelpattern.PipelineI#setTask(int, parallelpattern.TaskI)
	 */
	@Override
	public void setTask(int workerid, TaskI t) {

		this.tasks.add(workerid, t);
	}

	public void appendTask(TaskI t) {
		this.tasks.add(t);

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see parallelpattern.PipelineI#setConnections()
	 */
	@Override
	public void setConnections() {
		this.connectors = new Vector<FIFOBuffer>();
		for (int i = 0; i < workers.size() - 1; i++) {
			this.connectors.add(new FIFOBuffer());
		}

	}

	public int countWorkers() {
		return this.workers.size();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see parallelpattern.PipelineI#excute()
	 */
	@Override
	public void excute() {
		setConnections();

		// strange behavior of workers.size()
		// int workerEnd=this.workers.size()-1;
		// if (dbg)System.err.println(workerEnd);
		// if (dbg)System.err.println(workers.size()-1);
		//

		for (int i = 0; i < workerCount; i++) {
			if (i == 0) {
				this.workers.add(i,
						new Stage(i, null, connectors.get(i), tasks.get(i)));
				if (dbg)
					System.err.println(i);
				if (dbg)
					System.err.println((workers.size() - 1));
			} else if (i == (workerCount - 1)) {
				if (dbg)
					System.err.println(i);
				workers.add(i,
						new Stage(i, connectors.get(i - 1), null, tasks.get(i)));

			} else {
				if (dbg)
					System.err.println(i);
				workers.add(i,
						new Stage(i, connectors.get(i - 1), connectors.get(i),
								tasks.get(i)));
			}
		}

	}

	public void allStop() {

		for (int i = 0; i < workerCount; i++) {
			if ((workers.get(i).isStageAlive())
					|| (!workers.get(i).isInterrupted())) {
				if (dbg)
					System.err.println("\n" + workers.get(i).getName()
							+ " is alive");
				try {
					workers.get(i).join();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					System.err.println("\n" + workers.get(i).getName() + " "
							+ workers.get(i).currentThread());
					e.printStackTrace();
				}
				workers.get(i).stopStage();
				if (dbg)
					System.err.println("\n" + workers.get(i).getName() + " "
							+ workers.get(i).isAlive());

			}
		}
	}

}
